package com.eedi.framework.oauth2.convert;

import cn.hutool.core.collection.CollUtil;
import com.eedi.framework.common.util.object.BeanUtils;
import com.eedi.framework.oauth2.dal.dataobject.SysOAuth2AccessTokenDO;
import com.eedi.framework.oauth2.controller.sys.vo.auth.SysAuthLoginResp;
import com.eedi.framework.oauth2.controller.sys.vo.auth.SysAuthPermissionInfoResp;
import com.eedi.framework.user.controller.sys.vo.SysUserLoginInfoResp;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import org.slf4j.LoggerFactory;
import com.eedi.framework.permission.dal.dataobject.SysRoleDO;
import com.eedi.framework.permission.dal.dataobject.SysMenuDO;

import java.util.*;

import static com.eedi.framework.common.util.collection.CollectionUtils.convertSet;
import static com.eedi.framework.common.util.collection.CollectionUtils.filterList;
import static com.eedi.framework.permission.dal.dataobject.SysMenuDO.SYS_ID_ROOT;

@Mapper
public interface SysAuthConvert {

    SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class);

    SysAuthLoginResp convert(SysOAuth2AccessTokenDO bean);

    default SysAuthPermissionInfoResp convert(SysUserLoginInfoResp sysUser, List<SysRoleDO> roleList, List<SysMenuDO> menuList) {
        return SysAuthPermissionInfoResp.builder()
                .user(BeanUtils.toBean(sysUser, SysAuthPermissionInfoResp.UserVO.class))
                .roles(convertSet(roleList, SysRoleDO::getSysRoleCode))
                // 权限标识信息
                .permissions(convertSet(menuList, SysMenuDO::getSysMenuPermission))
                // 菜单树
                .menus(buildMenuTree(menuList))
                .build();
    }

    SysAuthPermissionInfoResp.MenuVO convertTreeNode(SysMenuDO menu);

    /**
     * 将菜单列表，构建成菜单树
     *
     * @param menuList 菜单列表
     * @return 菜单树
     */
    default List<SysAuthPermissionInfoResp.MenuVO> buildMenuTree(List<SysMenuDO> menuList) {
        if (CollUtil.isEmpty(menuList)) {
            return Collections.emptyList();
        }
        // 移除按钮
//        menuList.removeIf(menu -> menu.getSysMenuType().equals(SysMenuTypeEnum.BUTTON));
        // 排序，保证菜单的有序性
        menuList.sort(Comparator.comparing(SysMenuDO::getSysMenuSort));
        // 构建菜单树
        // 使用 LinkedHashMap 的原因，是为了排序 。实际也可以用 Stream API ，就是太丑了。
        Map<String, SysAuthPermissionInfoResp.MenuVO> treeNodeMap = new LinkedHashMap<>();
        menuList.forEach(menu -> treeNodeMap.put(menu.getSysMenuId(), SysAuthConvert.INSTANCE.convertTreeNode(menu)));
        // 处理父子关系
        treeNodeMap.values().stream().filter(node -> !node.getParentSysMenuId().equals(SYS_ID_ROOT)).forEach(childNode -> {
            // 获得父节点
            SysAuthPermissionInfoResp.MenuVO parentNode = treeNodeMap.get(childNode.getParentSysMenuId());
            if (parentNode == null) {
                LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]",
                        childNode.getSysMenuId(), childNode.getParentSysMenuId());
                return;
            }
            // 将自己添加到父节点中
            if (parentNode.getChildren() == null) {
                parentNode.setChildren(new ArrayList<>());
            }
            parentNode.getChildren().add(childNode);
        });
        // 获得到所有的根节点
       return filterList(treeNodeMap.values(), node -> SYS_ID_ROOT.equals(node.getParentSysMenuId()));
    }

//    SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO);
//
//    SmsCodeSendReqDTO convert(AuthSmsSendReqVO reqVO);
//
//    SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp);

}
